package com.stmt.stmtdesktop.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import lombok.SneakyThrows;

/**
 * @author liangbo
 */
public class NetUtil {

  private static final DelayQueue<DelayMessage> MESSAGE_QUEUE = new DelayQueue<>();

  private static final List<Consumer<String>> SEND_LISTENER = new ArrayList<>();
  private static DatagramSocket server;
  private static volatile boolean start = false;
  private static final Charset CHARSET = Charset.forName("GBK");


  public static void addSendListener(Consumer<String> listener) {
    SEND_LISTENER.add(listener);
  }


  public static void sendMessage(long time, String message) {
    MESSAGE_QUEUE.add(new DelayMessage(time, message));
  }

  public static String sendUdp(String host, Integer port, String data) throws Exception {
    InetAddress address = InetAddress.getByName(host);
    DatagramPacket packet = new DatagramPacket(data.getBytes(CHARSET), data.length(), address, port);
    byte[] data2 = new byte[1024];
    DatagramPacket packet2 = new DatagramPacket(data2, data2.length);

    try (DatagramSocket socket = new DatagramSocket()) {

      socket.send(packet);

      socket.receive(packet2);
    }
    return new String(data2, 0, packet2.getLength());
  }

  public static void closeUdp() {
    start = false;
    if (server != null) {
      server.close();
    }
  }

  public static synchronized void startUdp(String host, Integer localPort, Consumer<DatagramPacket> receiver) throws Exception {
    if (server != null) {
      server.close();
    }
    InetAddress addr = InetAddress.getByName(host);

    server = new DatagramSocket();
    start = true;

    CompletableFuture.allOf(
        CompletableFuture.runAsync(() -> {
          System.out.println("启动监听");
          while (start) {
            byte[] recvBuf = new byte[1024];
            DatagramPacket recvPacket = new DatagramPacket(recvBuf, recvBuf.length);
            try {
              server.receive(recvPacket);
              String recvStr = new String(recvPacket.getData(), 0, recvPacket.getLength(),CHARSET);
              System.out.println("接收指令 " + recvStr);
              receiver.accept(recvPacket);
            } catch (IOException e) {
              e.printStackTrace();
            }
          }
        }),
        CompletableFuture.runAsync(() -> {
          System.out.println("启动发送");
          while (start) {
            DelayMessage message;
            try {
              message = MESSAGE_QUEUE.poll(1, TimeUnit.SECONDS);
              if (message == null) {
                continue;
              }
              System.out.println("发送指令 " + message);
              byte[] sendBuf = message.message().getBytes(CHARSET);
              DatagramPacket sendPacket = new DatagramPacket(sendBuf, sendBuf.length, addr, localPort);
              server.send(sendPacket);
              SEND_LISTENER.forEach(c -> c.accept(message.message()));
            } catch (Exception e) {
              e.printStackTrace();
            }
          }
        })
    ).join();
  }
}
